 // ---------------------------------------------------------------------------------------------------------------------------------
// Core Control File for PCMod
// [SERVERSIDE]
// Revision: 2
// ---------------------------------------------------------------------------------------------------------------------------------

// ---------------------------------------------------------------------------------------------------------------------------------
// Define core table
// ---------------------------------------------------------------------------------------------------------------------------------
PCMod = {}
PCMod.Exists = true
PCMod.Version = "1.0.2"
PCMod.Routers = {}

PCLIB = {} -- Program Libraries

Msg( "=== PCMod Installed ===\n" )
Msg( "== PCMod Serverside OS (Release v" .. PCMod.Version .. ") Initialized ==\n" )


// ---------------------------------------------------------------------------------------------------------------------------------
// Add all the clientside files
// ---------------------------------------------------------------------------------------------------------------------------------

AddCSLuaFile( "pcmodcore/cl_vgui.lua" ) -- Core VGUI File
AddCSLuaFile( "pcmodcore/cl_pcscreen.lua" ) -- Core PC Screen Control File
AddCSLuaFile( "pcmodcore/cl_letter.lua" ) -- Letter Control File
AddCSLuaFile( "pcmodcore/cl_dmenu.lua" ) -- DInterface Library
AddCSLuaFile( "pcmodcore/cl_desktopicons.lua" ) -- Desktop Icons Control File

AddCSLuaFile( "pcbeamvars/cl_pcbeamvars.lua" ) -- BeamVars Library

AddCSLuaFile( "cl_serverapps.lua" ) -- BeamVars Library

AddCSLuaFile( "cl_themes.lua" ) -- Theme Loading
AddCSLuaFile( "themes/th_default-blue.lua" ) -- Default Theme
AddCSLuaFile( "themes/th_default-red.lua" ) -- Default Theme

for k, v in pairs( file.FindInLua( "cvgui/*.lua" ) ) do
	AddCSLuaFile( "cvgui/" .. v ) -- Every item in cvgui folder
end

for k, v in pairs( file.FindInLua( "pclibs/*.lua" ) ) do
	AddCSLuaFile( "pclibs/" .. v ) -- Every item in pclibs folder
end


// ---------------------------------------------------------------------------------------------------------------------------------
// Load all libraries
// ---------------------------------------------------------------------------------------------------------------------------------
for k, v in pairs( file.FindInLua( "pclibs/*.lua" ) ) do
	include( "pclibs/" .. v )
end


// ---------------------------------------------------------------------------------------------------------------------------------
// Include all the important core files
// ---------------------------------------------------------------------------------------------------------------------------------

include( "sv_programs.lua" ) -- Program Loading File
include( "pcbeamvars/sv_pcbeamvars.lua" ) -- PC Beam Vars Library
include( "sv_serverapps.lua" ) -- Server Apps Loading File


// ---------------------------------------------------------------------------------------------------------------------------------
// Define all the important globals
// ---------------------------------------------------------------------------------------------------------------------------------

PData = {} -- Program Data

// -- * CONFIGURABLE INFORMATION * --

	PCMod.TimedMessage = true -- Set this to false to stop the message that comes up every 3 minutes.
	PCMod.CustomTags = true -- Set this to true to change sv_tags to 'PCMod'
	PCMod.WirelessRange = 350 -- Change this to alter the wireless range of a laptop
	
// -- * _________________________ *--

PacketPath = {} -- Network Path-Finding

Msg( "PCMod -> Core Loaded\n" )


// ---------------------------------------------------------------------------------------------------------------------------------
// Add_VGUI_Mat: Adds a material to be downloaded (materials/vgui/*)
// ---------------------------------------------------------------------------------------------------------------------------------
function Add_VGUI_Mat( mat )
	resource.AddFile( "materials/vgui/" .. mat .. ".vmt" )
	resource.AddFile( "materials/vgui/" .. mat .. ".vtf" )
end

function Add_Model( mdl )
	resource.AddFile( "models/" .. mdl .. ".mdl" )
	resource.AddFile( "models/" .. mdl .. ".phy" )
	resource.AddFile( "models/" .. mdl .. ".vvd" )
	resource.AddFile( "models/" .. mdl .. ".sw.vtx" )
	resource.AddFile( "models/" .. mdl .. ".dx80.vtx" )
	resource.AddFile( "models/" .. mdl .. ".dx90.vtx" )	
end

// ---------------------------------------------------------------------------------------------------------------------------------
// InitPCMod: Initialise Hook: Initialises the addon
// ---------------------------------------------------------------------------------------------------------------------------------
function InitPCMod()
	// Add our resource files
	Add_VGUI_Mat( "pc_screen1" )
	Add_VGUI_Mat( "pc_screen2" )
	Add_VGUI_Mat( "pc_screen3" )
	
	Add_VGUI_Mat( "glossyblue" )
	Add_VGUI_Mat( "glossyblue-right" )
	Add_VGUI_Mat( "glossyblue-left" )
	Add_VGUI_Mat( "glossyblue-middle" )
	
	Add_VGUI_Mat( "glossywhite" )
	Add_VGUI_Mat( "glossywhite-right" )
	Add_VGUI_Mat( "glossywhite-left" )
	Add_VGUI_Mat( "glossywhite-middle" )
	
	Add_VGUI_Mat( "lowerbar-right" )
	
	Add_VGUI_Mat( "connect" )
	Add_VGUI_Mat( "disconnect" )
	Add_VGUI_Mat( "transmit" )
	Add_VGUI_Mat( "transmit_blue" )
	
	Add_VGUI_Mat( "icons/goldstar" )
	Add_VGUI_Mat( "icons/ico_app" )
	Add_VGUI_Mat( "icons/ico_console" )
	Add_VGUI_Mat( "icons/ico_pong" )
	Add_VGUI_Mat( "icons/ico_ctrl" )
	Add_VGUI_Mat( "icons/ico_wire" )
	
	Add_VGUI_Mat( "entities/pcmod_installdisk" )
	Add_VGUI_Mat( "entities/pcmod_laptopcase" )
	Add_VGUI_Mat( "entities/pcmod_networktester" )
	
	// Custom Models
	Add_Model( "laptop/laptop" )
	Add_Model( "GraffitiRTST/creative_woofer" )
	Add_Model( "GraffitiRTST/creative_volume" )
	
	// Laptop Material
	resource.AddFile( "materials/models/laptop/laptop.vtf" )
	resource.AddFile( "materials/models/laptop/laptop_normal.vtf" )
	resource.AddFile( "materials/models/laptop/laptop.vmt" )
	
	// Speaker Materials
	resource.AddFile( "materials/models/GraffitiRTST/creative_woofer/creative_woofer.vtf" )
	resource.AddFile( "materials/models/GraffitiRTST/creative_woofer/creative_woofer.vmt" )
	
	resource.AddFile( "materials/models/GraffitiRTST/creative_volume/creative_volume.vtf" )
	resource.AddFile( "materials/models/GraffitiRTST/creative_volume/creative_volume.vmt" )
	
	// Setup a timer that prints a message to everybody every 180 seconds
	if (PCMod.TimedMessage) then
		timer.Create( "PCMod_HintTimer", 180, 0, function()
			for k,v in pairs( player.GetAll() ) do
				v:PrintMessage( HUD_PRINTTALK, "This server uses the PCMod Addon Release V" .. PCMod.Version )
			end
		end )
	end
	
	// If we are told to, add custom tags
	if (PCMod.CustomTags) then game.ConsoleCommand( "sv_tags PCMod\n" ) end
end
hook.Add( "Initialize", "PCMod_InitAddon", InitPCMod )

// ---------------------------------------------------------------------------------------------------------------------------------
// GetSubnet: Pulls the subnet out of an IP address
// ---------------------------------------------------------------------------------------------------------------------------------
function GetSubnet( IP )
	return (string.Explode( ".", IP )[3])
end

// ---------------------------------------------------------------------------------------------------------------------------------
// CC_PC: ConCommand: Handles 'pc_command' con command, and directs it to the player's current PC
// ---------------------------------------------------------------------------------------------------------------------------------
function CC_PC( ply, command, args )
	// Check if the player is using a PC
	if (!ply.CurrentPC) then return end
	if (!ply.CurrentPC:IsValid()) then return end
	local obj = ply.CurrentPC
	
	// Get the command, then remove it from the table
	pc_com = args[1]
	table.remove( args, 1 )
	
	// Call the command
	obj:ExecuteCommand( ply, pc_com, args )
end
concommand.Add( "pc_command", CC_PC )

// DeliveryCode:
// 0 = Cannot Deliver
// 1 = Delivered
// 2 = Destination not found
// 3 = No Network
// 4 = Packet Denied: Closed Port
// 5 = Packet Denied: Blocked IP
// 6 = Packet Denied: Invalid packet

// ---------------------------------------------------------------------------------------------------------------------------------
// DeliveryStatus: Converts a numeric delivery code into a string
// ---------------------------------------------------------------------------------------------------------------------------------
function DeliveryStatus( response )
	if (response == 0) then return "Cannot Deliver" end
	if (response == 1) then return "Packet Delivered" end
	if (response == 2) then return "Destination Not Found" end
	if (response == 3) then return "No Network Availible" end
	if (response == 4) then return "Packet Denied: Closed Port" end
	if (response == 5) then return "Packet Denied: IP Blocked" end
	if (response == 6) then return "Packet Denied: Invalid Packet" end
	return "Unknown Status"
end

// ---------------------------------------------------------------------------------------------------------------------------------
// PCMOD_Spawn: PlayerSpawn Hook: Sends the player information about the server
// ---------------------------------------------------------------------------------------------------------------------------------
function PCMOD_Spawn( ply )
	if (ply.PCR) then return end
	// umsg.Start( "_sapp", ply )
		// umsg.Short( table.Count( PCMod.ServerApps ) )
		for k, v in pairs( PCMod.ServerApps ) do
			local str = k .. "#" .. v.Name
			// if (v:Useable()) then umsg.String( str ) end
		end
	// umsg.End()
	ply.PCR = true
end
hook.Add( "PlayerSpawn", "PCMod_Spawn", PCMOD_Spawn )

// ---------------------------------------------------------------------------------------------------------------------------------
// ComposePacket: Sends a packet to the destination server, via the player's current PC
// ---------------------------------------------------------------------------------------------------------------------------------
function ComposePacket( ply, dest, port, body, pass )
	local obj = ply.CurrentPC
	if (!obj) then return 0 end
	packet = { obj.Data[obj:EntIndex()].IP, dest, port, body }
	if (pass) then packet[5] = pass end
	return obj:SendPacket( packet )
end

// ---------------------------------------------------------------------------------------------------------------------------------
// OpenPort: Opens a port on a PC
// ---------------------------------------------------------------------------------------------------------------------------------
function OpenPort( ply, port )
	local obj = ply.CurrentPC
	if (!obj) then return end
	table.insert( obj.Data[obj:EntIndex()].PortList, { port, "prog" } )
end

// ---------------------------------------------------------------------------------------------------------------------------------
// ClosePort: Closes a port on a PC
// ---------------------------------------------------------------------------------------------------------------------------------
function ClosePort( ply, port )
	local obj = ply.CurrentPC
	if (!obj) then return end
end

// ---------------------------------------------------------------------------------------------------------------------------------
// SendClientProgram: Tells the client to load a program
// ---------------------------------------------------------------------------------------------------------------------------------
function SendClientProgram( ply, ProgramName )
	if (!ply) then return end
	umsg.Start( "_pcmod_runprog", ply )
	umsg.String( ProgramName )
	umsg.End()
end

// ---------------------------------------------------------------------------------------------------------------------------------
// SendClientWindow: Tells the client to load a window
// ---------------------------------------------------------------------------------------------------------------------------------
function SendClientWindow( ply, WindowName )
	if (!ply) then return end
	umsg.Start( "_pcmod_progwindow", ply )
	umsg.String( WindowName )
	umsg.End()
	local obj = ply.CurrentPC
	if (!obj) then return end
	obj.Data[obj:EntIndex()].WindowName = WindowName
end

// ---------------------------------------------------------------------------------------------------------------------------------
// UnloadProgram: Tells the client to unload a program
// ---------------------------------------------------------------------------------------------------------------------------------
function UnloadProgram( ply )
	if (!ply) then return end
	umsg.Start( "_pcmod_killprog", ply )
	umsg.End()
	local obj = ply.CurrentPC
	if (!obj) then return end
	obj:UnloadProgram()
end

// ---------------------------------------------------------------------------------------------------------------------------------
// BeamData_String: Sends the client a string to be handled by the program
// ---------------------------------------------------------------------------------------------------------------------------------
function BeamData_String( ply, tag, data )
	if (!ply) then return end
	umsg.Start( "_pcmod_beamdata_str", ply )
		umsg.String( tag )
		umsg.String( data )
	umsg.End()
end

// ---------------------------------------------------------------------------------------------------------------------------------
// BeamData_Int: Sends the client a number to be handled by the program
// ---------------------------------------------------------------------------------------------------------------------------------
function BeamData_Int( ply, tag, data )
	if (!ply) then return end
	umsg.Start( "_pcmod_beamdata_int", ply )
		umsg.String( tag )
		umsg.Short( data )
	umsg.End()
end

// ---------------------------------------------------------------------------------------------------------------------------------
// BeamData_Float: Sends the client a float to be handled by the program
// ---------------------------------------------------------------------------------------------------------------------------------
function BeamData_Float( ply, tag, data )
	if (!ply) then return end
	umsg.Start( "_pcmod_beamdata_float", ply )
		umsg.String( tag )
		umsg.Float( data )
	umsg.End()
end